package main

import (
	"fmt"
	"asd/bintree"
	"asd/set"
	"asd/list"
)

func print(n *bintree.BTNode, uData interface{}) bool {
	fmt.Println(" ", n)
	return true
}

func printL(n *list.LNode, uData interface{}) bool {
	fmt.Println(" ", n)
	return true
}

func exampleBtree() {	
	base := bintree.NewBTree()
	node := bintree.NewBTNode(5)
	n1 := bintree.NewBTNode(7)
	n2 := bintree.NewBTNode(10)
	n3 := bintree.NewBTNode(11)
	n4 := bintree.NewBTNode(12)
	n5 := bintree.NewBTNode(13)
	n6 := bintree.NewBTNode(15)

	base.SetRoot(node)
	fmt.Println(base)
	
	_, err := base.SetRoot(n1)
	fmt.Println(err)
	_, err = node.InsertLeft(n1)
	fmt.Println(err)
	_, err = node.InsertLeft(n2)
	fmt.Println(err)
	base.Root().Walk(print, nil)
	fmt.Println("Segment1")
	_, err = node.InsertRight(n2)
	base.Root().Walk(print, nil)
	fmt.Println("Segment2")
	n3.InsertLeft(n4)
	n4.InsertLeft(n5)
	n4.InsertRight(n6)
	n2.AppendLeft(n3)
	fmt.Println(base)
	base.Root().Walk(print, nil)
	n4.Detach()
	fmt.Println(base)
	n4.Walk(print, nil)
}

type Int struct {
	int
}

func (i Int)Less(j bintree.Comparable) bool {
	return i.int < j.(Int).int
}

func (i Int)More(j bintree.Comparable) bool {
	return i.int > j.(Int).int
}

func (i Int)Equal(j bintree.Comparable) bool {
	return i.int == j.(Int).int
}

func exampleSorted() {
	base := bintree.NewBTree()
	base.Duplicate(true)
	a := Int{1}
	b := Int{2}
	base.InsertSorted(a)
	base.InsertSorted(b)
	fmt.Println(base)
	fmt.Println("END")
	base.InsertSorted(Int{7})
	base.InsertSorted(Int{9})
	base.InsertSorted(Int{12})
	base.InsertSorted(Int{11})
	base.InsertSorted(Int{9})
	base.Root().Walk(print, nil)
	fmt.Println(a.Less(b))
	element, err := base.Search(Int{13})
	fmt.Println(element, err)
	element, err = base.Search(Int{11})
	fmt.Println(err)
	fmt.Println(base.Remove(element))
	base.Root().Walk(print, nil)
}

func exampleSet() {
	base := set.NewSet()
	base.Insert(Int{10})
	base.Insert(Int{10})
	base.Insert(Int{10})
	base.Insert(Int{9})
	base.Insert(Int{10})
	base.Insert(Int{11})
	base.Insert(Int{12})
	base.Insert(Int{13})
	fmt.Println("here is the starting point")
	fmt.Println(base)
	base.Remove(Int{11})
	fmt.Println(base)
	fmt.Println(base.Contains(Int{11}))
	fmt.Println(base.Contains(Int{10}))
}

func exampleSetUnion() {
	fmt.Println("Start Set Operation tests")
	base := set.NewSet()
	base2:= set.NewSet()
	base2.Insert(Int{10})
	base2.Insert(Int{15})
	base.Insert(Int{9})
	base.Insert(Int{13})
	base3 := base.Union(base2)
	fmt.Println(base3)
	base2.Insert(Int{9})
	base4 := base.Intersection(base2)
	fmt.Println(base4)
}

func exampleList() {
	base := list.NewLList()
	n1 := list.NewLNode(Int{1})
	base.SetRoot(n1)
	n2 := list.NewLNode(Int{2})
	n3 := list.NewLNode(Int{3})
	n2.AppendBefore(n3)
	n4 := list.NewLNode(Int{4})
	n3.AppendBefore(n4)
	n5 := list.NewLNode(Int{5})
	n6 := list.NewLNode(Int{6})
	n5.AppendBefore(n6)
	n7 := list.NewLNode(Int{7})
	n6.AppendBefore(n7)
	n8 := list.NewLNode(Int{8})
	n7.AppendBefore(n8)
	n1.AppendAfter(n4)
	n4.AppendAfter(n8)
	fmt.Println(base)
	base.Root().Walk(printL, nil)
	base1 := list.NewLList()
	m1 := list.NewLNode(Int{1})
	base1.SetRoot(m1)
	m2 := list.NewLNode(Int{2})
	m3 := list.NewLNode(Int{3})
	m2.AppendAfter(m3)
	m4 := list.NewLNode(Int{4})
	m3.AppendAfter(m4)
	m5 := list.NewLNode(Int{5})
	m6 := list.NewLNode(Int{6})
	m5.AppendAfter(m6)
	m7 := list.NewLNode(Int{7})
	m6.AppendAfter(m7)
	m8 := list.NewLNode(Int{8})
	m7.AppendAfter(m8)
	m1.AppendAfter(m2)
	m4.AppendAfter(m5)
	base1.Remove(m5)
	fmt.Println(base1)
	base1.Root().Walk(printL, nil)
}

func main() {
	fmt.Println("this is my main example")
	exampleBtree()
	exampleSorted()
	exampleSet()
	exampleSetUnion()
	exampleList()
}